Repository navigation
Conversation
…ption `extension search` and `extension info` indexed a catalog entry's name, version and description directly, so an entry without one of them made both commands exit with a KeyError, and search never listed the entries after it. Catalog entries are not validated field by field on purpose, and `extension update` already skips a versionless entry (github#5108). Read the three fields with .get(): `unknown` for a missing version (as `extension add` and installed-extension info show it), the extension ID for a missing name, and an empty description. Assisted-by: Codex CLI (model: gpt-6.1-sol, autonomous) Assisted-by: Claude Code (model: claude-opus-5-5, autonomous)
There was a problem hiding this comment.
🟢 Approval recommended
The changes address missing catalog metadata with safe fallbacks while preserving search behavior and Rich escaping, alongside regression coverage for incomplete entries.
No open issues 🎉
What changed in this PR
Updates specify extension search and specify extension info to handle catalog entries missing name, version, or description without raising KeyError.
Changes:
- Added fallbacks for missing metadata: extension ID for names,
unknownfor versions, and an empty description. - Preserved Rich markup escaping and search filtering behavior.
- Added cached catalog fixtures and parameterized CLI regression tests.
| File | Description |
|---|---|
tests/specify_cli/extensions/test_command_search.py |
Verifies incomplete entries display correctly and filtering continues to work. |
tests/specify_cli/extensions/test_command_info.py |
Verifies incomplete and complete catalog entries display successfully. |
tests/specify_cli/extensions/conftest.py |
Adds cached catalog fixtures covering missing fields and Rich markup. |
src/specify_cli/extensions/command_search.py |
Safely renders incomplete catalog metadata during search. |
src/specify_cli/extensions/command_info.py |
Safely renders incomplete catalog metadata in extension details. |
Review effort: Lite (auto)
|
Please fix test & lint errors |
The autouse fixtures request monkeypatch before temp_dir, so the cwd was restored only after temp_dir's rmtree. Windows refuses to delete the current directory (WinError 32), and every case errored at teardown. Assisted-by: Claude Code (model: claude-opus-5-5, autonomous)
|
Fixed in ad8c909. The autouse fixtures request Drafted on behalf of @kartsan03 by Claude Code (model: claude-opus-5-5, autonomous) |
There was a problem hiding this comment.
🟢 Approval recommended
The implementation adds safe fallbacks for incomplete catalog metadata and includes focused regression coverage for search filtering and info rendering, with only a non-blocking assertion-strengthening nit noted.
No open issues 🎉
Review effort: Lite (auto)
Description
specify extension searchandspecify extension infoindexed a catalog entry'sname,versionanddescriptiondirectly, so an entry missing one of them made both commands exit 1 with aKeyError(#5307). Search stopped at that entry, so the extensions after it were never listed. Catalog entries are kept without per-field validation on purpose (_get_merged_extensions: "one malformed entry shouldn't poison an otherwise valid catalog"), and #5108 madeextension updateskip a versionless entry for the same reason.The two display paths now read those fields with
.get(), using the fallbacks the extensions code already has:unknownfor a missing version (as inextension addandinfofor an installed extension), the extension ID for a missing name, and an empty description (assearch()already treats it when filtering). Values are still escaped for Rich as before.Repro with the real CLI: a project whose cached catalog holds one complete entry (
healthy) and one entry (example) missing a single field. Steps are in #5307.exampleis missingmain(c438494)versionextension searchKeyError: 'version'Example (vunknown)andHealthy (v2.0.0)versionextension info exampleKeyError: 'version'Example (vunknown)nameextension searchKeyError: 'name'example (v1.0.0)andHealthy (v2.0.0)nameextension info exampleKeyError: 'name'example (v1.0.0)descriptionextension searchKeyError: 'description'descriptionextension info exampleKeyError: 'description'Fixes #5307
Testing
uv run specify --helpuv sync && uv run pytestA new fixture in
tests/specify_cli/extensions/conftest.py,incomplete_catalog_entry, writes a fresh catalog cache with the incomplete entry and a complete sibling, and fails the test if the catalog is fetched from the network. It runs four cases: no version, no name, no description, and a version holding Rich markup.TestExtensionSearchCLI.test_search_shows_incomplete_catalog_entry: unfiltered search lists both entries with the expected headers, andsearch Healthystill filters the incomplete one out.TestExtensionInfoCLI.test_info_shows_incomplete_catalog_entry:info exampleandinfo healthyboth exit 0 with the expected headers.With
command_search.pyandcommand_info.pyreverted tomain, the three missing-field cases of each test fail (6 of 8). The markup cases pass onmaintoo, since escaping already worked.Full suite on Linux, Python 3.13: 13961 passed, 449 skipped, 1 failed (
pytest -n 2, 7 min). The failure,test_version_execution.py::TestWindowsUvToolEnvironment::test_non_windows_uv_tool_dry_run_still_previews_installer, fails the same way onmainhere: Rich wraps the dry-run output, and my checkout's venv path is long enough to be split mid-path. Ruff 0.15.0 (ruff check src tests) passes. I haven't run it on Windows.AI Disclosure
AI disclosure: Codex CLI (model: gpt-6.1-sol, reasoning effort xhigh, autonomous, offline sandbox) found the missing-
versioncrash and wrote the first fix and tests. Claude Code (model: claude-opus-5-5, autonomous) extended the fix and tests tonameanddescription, reran the repro with the real CLI onmainand the branch, ran the full suite and lint, and drafted this description. The commit carriesAssisted-by:trailers for both.